package com.borqsprocessmanager;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;

import com.borqsprocessmanager.info.ReceiverProcessInfo;

public class ProcessSettingManager {
    private static final String TAG = "ProcessSettingManager";

    // private Context mContext;
    private Process process = null;
    private ActivityManager mActivityManager;

    public ProcessSettingManager() {
        mActivityManager = (ActivityManager) App.mContext
                .getSystemService(Context.ACTIVITY_SERVICE);
    }

    /**
     * 
     * @param receivers
     * @param action
     *            true-enable,false-disable
     */
    public static void operatingAplacation(ArrayList<String> receivers,
            boolean action) {
        for (String component : receivers) {
            StringBuffer sb = new StringBuffer();
            if (action) {
                sb.append("pm enable ");
            } else {
                sb.append("pm disable ");
            }
            sb.append(component);
            Log.v(TAG, "operatingAplacation===" + sb.toString());
            String res = runRootCommand(sb.toString());
            Log.v(TAG, "operatingAplacation_res===" + res);
        }
    }

    public void requestSuperUser(Context context) {
        try {
            process = Runtime.getRuntime().exec("su");
        } catch (IOException e) {
            Toast.makeText(context, "Eor", 100).show();
            e.printStackTrace();
        }
    }

    // public static boolean isRooted() {
    // // 检测是否ROOT过
    // boolean flag = false;
    // try {
    // flag = runRootCommand("ls /data/");
    // if (flag)
    // flag = true;
    // } catch (Exception e1) {
    // e1.printStackTrace();
    // }
    // return flag;
    // }

    public static boolean isRooted() {
        // 检测是否ROOT过
        String flag = null;
        try {
            com.borqsprocessmanager.util.Log.v(TAG, "isRooted");
            flag = runRootCommand("ls");
            com.borqsprocessmanager.util.Log.v(TAG, "flag===" + flag);
            if (flag != null && !flag.equals(""))
                return true;
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return false;
    }

    public void closeSuperUser() {
        if (process != null) {
            process.destroy();
        }
    }

    public static String runRootCommand(String command) {
        // StringBuffer result = new StringBuffer();
        Process process = null;
        DataOutputStream os = null;
        DataInputStream is = null;
        try {
            com.borqsprocessmanager.util.Log.v(TAG, "command===" + command);
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            is = new DataInputStream(process.getInputStream());
            os.writeBytes(command + "\n");
            os.writeBytes("exit \n");
            os.flush();
            byte[] re = new byte[1];
            // while (is.read(re) != -1) {
            // for (int i = 0; i < 1; i++) {
            String result = is.readLine();
            // is.read(re);
            // String result = new String(re);
            com.borqsprocessmanager.util.Log.v(TAG, "runRootCommand_result==="
                    + result);
            // result = result.append(re);
            // }
            // }
            process.waitFor();
            return result;
        } catch (Exception e) {
            Log.v("*** DEBUG ***", "Unexpected error - Here is what I know: "
                    + e.getMessage());
            return null;
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (is != null) {
                    is.close();
                }
                if (process != null) {
                    process.destroy();
                }
            } catch (Exception e) {

            }
        }
    }

    /**
     * android.net.conn.CONNECTIVITY_CHANGE
     * 
     * @param action
     * @throws NameNotFoundException
     */
    public static ArrayList<ReceiverProcessInfo> getCompoentProcesslist(
            String action) throws NameNotFoundException {
        return getMapData(getCompoentProcessMap(action));
    }

    /**
     * android.net.conn.CONNECTIVITY_CHANGE
     * 
     * @param action
     * @throws NameNotFoundException
     */
    public static HashMap<String, ReceiverProcessInfo> getCompoentProcessMap(
            String action) throws NameNotFoundException {
        // ArrayList<ReceiverProcessInfo> resList = new
        // ArrayList<ReceiverProcessInfo>();
        HashMap<String, ReceiverProcessInfo> map = new HashMap<String, ReceiverProcessInfo>();
        PackageManager pm = App.mContext.getPackageManager();
        Intent intent = new Intent();
        intent.setAction(action);
        List<ResolveInfo> list = pm.queryBroadcastReceivers(intent,
                PackageManager.GET_DISABLED_COMPONENTS);
        Log.v(TAG, "queryBroadcastReceivers");
        if (list != null && list.size() > 0) {
            String res = "";
            for (int i = 0; i < list.size(); i++) {
                ActivityInfo info = list.get(i).activityInfo;
                String receivers = info.name;
                String packageName = info.packageName;
                String processName = info.processName;

                int isIndexOf = receivers.indexOf(packageName);
                if (isIndexOf == 0) {
                    String appName = (String) pm.getApplicationLabel(pm
                            .getApplicationInfo(packageName,
                                    PackageManager.GET_UNINSTALLED_PACKAGES));
                    ComponentName mComponentName = new ComponentName(
                            info.packageName, info.name);
                    int state = pm.getComponentEnabledSetting(mComponentName);

                    StringBuffer sb = new StringBuffer(receivers);
                    int componentCount = receivers.compareTo(packageName);
                    int classCount = receivers.indexOf("$");
                    sb.insert((sb.length() - componentCount), "/");
                    Log.v(TAG, "classCount===" + classCount + 1);
                    if (classCount > 0) {
                        sb.insert(classCount + 1, "\\");
                    }
                    res = sb.toString();
                    Log.v(TAG, i + "===RES===" + res);
                    Log.v(TAG, i + "===packageName===" + packageName);
                    Log.v(TAG, i + "===ProcessName===" + processName);
                    Log.v(TAG, state + "");

                    if (map.containsKey(packageName)) {
                        map.get(packageName).reivevers.add(res);
                    } else {
                        ReceiverProcessInfo rpInfo = new ReceiverProcessInfo();
                        rpInfo.setAppName(appName);
                        rpInfo.setPackageName(packageName);
                        rpInfo.setProcessName(processName);
                        rpInfo.setReivever(res);
                        rpInfo.setIsClose(state);
                        map.put(packageName, rpInfo);
                    }
                }
            }
        }
        return map;
    }

    /**
     * android.net.conn.CONNECTIVITY_CHANGE
     * 
     * @param action
     * @throws NameNotFoundException
     */
    public static ArrayList<ReceiverProcessInfo> getProcesslist(boolean isRoot,
            HashMap<String, ReceiverProcessInfo> mAutoStartMap,
            HashMap<String, ReceiverProcessInfo> actionMap)
            throws NameNotFoundException {
        ArrayList<ReceiverProcessInfo> resList = new ArrayList<ReceiverProcessInfo>();
        // ArrayList<ReceiverProcessInfo> resList = new
        // ArrayList<ReceiverProcessInfo>();
        HashMap<String, ReceiverProcessInfo> map = new HashMap<String, ReceiverProcessInfo>();
        PackageManager pm = App.mContext.getPackageManager();

        List<PackageInfo> list = pm
                .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
        Log.v(TAG, "queryBroadcastReceivers");
        if (list != null && list.size() > 0) {
            String res = "";
            for (int i = 0; i < list.size(); i++) {
                PackageInfo pckInfo = list.get(i);
                if (isSystemApp(pckInfo.applicationInfo)) {
                    ReceiverProcessInfo info = new ReceiverProcessInfo();
                    info.appName = pckInfo.applicationInfo.loadLabel(pm)
                            .toString();
                    info.packageName = pckInfo.packageName;
                    info.processName = pckInfo.applicationInfo.processName;
                    com.borqsprocessmanager.util.Log.v(TAG,
                            "getProcesslist_packageName===" + info.packageName);
                    if (actionMap.containsKey(info.packageName)) {
                        com.borqsprocessmanager.util.Log.v(TAG,
                                "actionMap.containsKey(info.processName)==="
                                        + info.packageName);
                        info.isClose = 2;
                    }
                    if (mAutoStartMap.containsKey(info.processName)) {
                        if (!isRoot) {
                            continue;
                        }
                        info.section = info.head_scheduled_running;
                        info.type = ReceiverProcessInfo.AUTOP_ROCESS;
                    } else {
                        info.section = info.head_more;
                        info.type = ReceiverProcessInfo.COMMON_PROCESS;
                    }
                    resList.add(info);
                }
            }
        }
        Collections.sort(resList);
        return resList;
    }

    public static boolean isSystemApp(ApplicationInfo applicationInfo) {
        if ((applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {

            return true;

        } else if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {

            return true;

        }
        return false;
    }

    public static HashMap<String, ArrayList<Integer>> getRunProcessAndServer() {
        ActivityManager am = (ActivityManager) App.mContext
                .getSystemService(Context.ACTIVITY_SERVICE);
        // 获取正在运行的应用
        HashMap<String, ArrayList<Integer>> runningProcessMap = new HashMap<String, ArrayList<Integer>>();
        List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();
        List<RunningServiceInfo> servers = am.getRunningServices(100);

        for (int i = 0; i < apps.size(); i++) {
            ArrayList<Integer> pidList = new ArrayList<Integer>();
            RunningAppProcessInfo app = apps.get(i);
            if (app.uid < 10000) {
                continue;
            }
            for (int j = 0; j < servers.size(); j++) {
                RunningServiceInfo server = servers.get(j);
                if (app.uid == server.uid) {
                    pidList.add(server.pid);
                }
            }
            if (pidList.size() > 0) {
                // pidList.add(app.pid);
                com.borqsprocessmanager.util.Log.v(TAG, "app.processName==="
                        + app.processName);
                runningProcessMap.put(app.pkgList[0], pidList);
            }
        }
        return runningProcessMap;
    }

    public static List<RunningAppProcessInfo> getRunProcess() {
        ActivityManager am = (ActivityManager) App.mContext
                .getSystemService(Context.ACTIVITY_SERVICE);
        // 获取正在运行的应用
        List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();
        for (RunningAppProcessInfo app : apps) {
            String[] pkgs = app.pkgList;
            com.borqsprocessmanager.util.Log.v(TAG, "size()==" + pkgs.length);
            for (String pkg : pkgs) {
                com.borqsprocessmanager.util.Log.v(TAG, "getRunProcess==="
                        + pkg);

            }
        }
        return apps;
    }

    public void killProcess(List<RunningAppProcessInfo> runProcess,
            HashMap<String, ReceiverProcessInfo> actionMap) {
        Log.v(TAG, "killProcess");
        for (RunningAppProcessInfo info : runProcess) {
            if (actionMap.containsKey(info.processName)) {
                String packageName = actionMap.get(info.pkgList[0]).packageName;
                if (!packageName.equals(getTaskTopPackageName())) {
                    Log.v(TAG, "kill_ProcessName===" + packageName);
                    runRootCommand("am force-stop " + packageName);
                }
            }
        }
    }

    public void killProcessNoRoot(List<RunningAppProcessInfo> runProcess,
            HashMap<String, ReceiverProcessInfo> actionMap) {
        for (RunningAppProcessInfo info : runProcess) {
            if (actionMap.containsKey(info.processName)) {
                String packageName = actionMap.get(info.pkgList[0]).packageName;
                if (!packageName.equals(getTaskTopPackageName())) {
                    Log.v(TAG, "kill_ProcessName===" + packageName);
                    mActivityManager.killBackgroundProcesses(packageName);
                }
            }
        }
    }

    private String getTaskTopPackageName() {
        return mActivityManager.getRunningTasks(1).get(0).topActivity
                .getPackageName();
    }

    public static ArrayList<ReceiverProcessInfo> getMapData(
            HashMap<String, ReceiverProcessInfo> map) {
        Log.v(TAG, "map.size===" + map.size());
        ArrayList<ReceiverProcessInfo> resList = new ArrayList<ReceiverProcessInfo>();
        Iterator<Entry<String, ReceiverProcessInfo>> iter = map.entrySet()
                .iterator();

        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            ReceiverProcessInfo info = (ReceiverProcessInfo) entry.getValue();
            resList.add(info);
        }
        Collections.sort(resList);
        return resList;
    }

    public static void uninstillApp(Context context, String packageName) {
        Uri uninstallUrl = Uri.parse("package:" + packageName);
        Intent intent = new Intent(Intent.ACTION_DELETE, uninstallUrl);
        context.startActivity(intent);
    }
}
